// MotionIndicator.v - Motion Indicator & Display
//
// Description:
// ------------
// Takes an encoded direction input and displays the robot characteristics 
// on the d3 seven segment display.
// 
// Adding FSM Mealy with Synchronous reset 
// State 1:Stop - Segment g on steady
// State 2:Turn Right 1X Speed - Chase clockwise 5 Hz
// State 3:Turn Right 2X Speed - Chase clockwise 10 Hz
// State 4:Turn Left 1X Speed - Chase counterclockwise 5 Hz
// State 5:Turn Left 2X Speed - Chase counterclockwise 10 Hz
// State 6:Forward - Segment a blinks at about 1 Hz
// State 7:Reverse - Segment d blinks at 1 Hz
//
// Input(s) :
// clk, motion_input
// Output(s):
// Hex-to-7Segment
//
// Copyright Jabeer Ahmed and Caleb Mathisen, 2014
// 
// Created By:      Caleb Mathisen
// Author(s) :      Jabeer Ahmed, Caleb Mathisen
// Last Modified:   1/18/2014
//
// Revision History:
// -----------------
///////////////////////////////////////////////////////////////////////////

`timescale  1 ns / 1 ns
module Motion_Indicator(
    //inputs
    input               clk,                // clock    
    input [7:0]         motion_input,    // motion indicator input (0-6) Hex 

    //outputs
    output reg [7:0]    d3 = 8'b11111111, // forces blank digit 
    output reg [31:0]   slow_clk_ivl  = 31'd20_000_000,   // 5 Hz
    output reg          set_clock     = 1'b1
);

// Rotation FSM CW or CCW
reg CW = 1'b1;          // CW=1 (CW), CW=0 (CCW)
reg FWD = 1'b1;     // FWD=1 (Forward), FWD=0 (Reverse) 
reg reset = 1'b0;
reg clock;                      // 5 Hz or 10 Hz
reg [2:0] state;

// Select one based on the input 

// 1 Hz (Forward or Reverse)
// 5 Hz (CW or CCW Slow)
// 10 Hz (CW or CCW Fast)

    localparam seg_a  = 8'b11111110;
    localparam seg_b  = 8'b11111101;
    localparam seg_c  = 8'b11111011;
    localparam seg_d  = 8'b11110111;
    localparam seg_e  = 8'b11101111;
    localparam seg_f  = 8'b11011111;
    localparam seg_g  = 8'b10111111;
    localparam seg_db = 8'b01111111;
    
    localparam dp        = 4'h0;
    localparam Stop      = 4'h1;
    localparam Right_1X  = 4'h2;
    localparam Right_2X  = 4'h3;
    localparam Left_1X   = 4'h4;
    localparam Left_2X   = 4'h5;
    localparam Forward   = 4'h6;
    localparam Reverse   = 4'h7;

    // localparam dp = 1; // decimal point is always off

always @(posedge clock)
    begin
        case (motion_input)
            Stop      : d3 = {dp, seg_g};
            Right_1X  : 
                begin
                    CW = 1;
                    slow_clk_ivl  = 31'd20_000_000;   // 5 Hz
                    set_clock     = 1'b1;
                    RotationFSM;                      // CW
                end
            Right_2X  : 
                begin
                    CW = 1;
                    slow_clk_ivl  = 31'd10_000_000;   // 10 Hz
                    set_clock     = 1'b1;
                    RotationFSM;                       // CW
                end
            Left_1X   : 
                begin
                    CW = 0;
                    slow_clk_ivl  = 31'd20_000_000;   // 5 Hz
                    set_clock     = 1'b1;
                    RotationFSM;                      // CCW
                end   
            Left_2X   : 
                begin
                    CW = 0;
                    slow_clk_ivl  = 31'd10_000_000;   // 10 Hz
                    set_clock     = 1'b1;
                    RotationFSM;                      // CCW
                end   
            Forward   : 
                begin
                    FWD = 1;
                    slow_clk_ivl  = 31'd100_000_000;   // 1 Hz
                    set_clock     = 1'b1;
                    FlashFSM;
                end
            Reverse   :
                begin
                    FWD = 0;
                    slow_clk_ivl  = 31'd100_000_000;   // 1 Hz
                    set_clock     = 1'b1;
                    FlashFSM;
                end
        endcase
    end


// CW = Clockwise, ~CW = Counter Clockwise
function RotationFSM;
always @(posedge clock)
   begin
      if (reset) state <= 1;
         else case(state)
      1: if (CW) 
           begin        
               d3 = {dp, seg_a};   // Segment a
               state <= 2;
         else 
           begin
               d3 = {dp, seg_f};   // Segment f
               state <= 6;
           end
      2: if (CW) 
           begin
               d3 = {dp, seg_b};  // Segment b
               state <= 3;        
           end
         else 
           begin
               d3 = {dp, seg_e};   // Segment e
               state <= 1;
           end
      3: if (CW) 
           begin
               d3 = {dp, seg_c};   // Segment c
               state <= 4;       
           end
         else 
           begin
               d3 = {dp, seg_d};   // Segment d
               state <= 2;
           end
      4: if (CW) 
           begin
               d3 = {dp, seg_d};   // Segment d 
               state <= 5;        
           end
         else 
           begin
               d3 = {dp, seg_c};   // Segment c
               state <= 3;
           end
      5: if (CW) 
           begin
               d3 = {dp, seg_e};   // Segment e
               state <= 6;    
           end
         else 
           begin
               d3 = {dp, seg_b};   // Segment b
               state <= 4;
           end
      6: if (CW) 
           begin
               d3 = {dp, seg_e};   // Segment f 
               state <= 1;     
           end
         else 
           begin
               d3 = {dp, seg_a};   // Segment a
               state <= 5;
           end
      default: state <= 1;
   end
endfunction     

function FlashFSM;
always @(posedge clock)
   begin
       //  Code here
       if (reset) state <= 7;
         else case(state)
    else case(state)
      7: if (FWD) 
           begin        
               d3 = {dp, seg_a};   // Segment a
               state <= 8;
           end
         else 
           begin
               d3 = {dp, seg_d};   // Segment d
               state <= 8;
           end
      8: if (FWD) 
           begin
               d3 = {dp, seg_d};  // Segment d
               state <= 7;        
           end
         else 
           begin
               d3 = {dp, seg_a};   // Segment a
               state <= 7;
           end
   end
endfunction 

endmodule
